package org.lex.dbq.view.browser;

import java.io.IOException;
import java.util.Arrays;

import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.ListViewer;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.ToolBar;
import org.lex.dbq.DBQApplication;
import org.lex.dbq.model.bo.BoUtils;
import org.lex.dbq.model.bo.CommonObject;
import org.lex.dbq.model.service.CommonService;
import org.lex.swt.SWTUtils;
import org.lex.swt.app.ActionService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class AbstractBrowser<T extends CommonObject> extends Composite implements ISelectionChangedListener {

	private ConnectAction connect = new ConnectAction();
	private AddAction add = new AddAction();
	private EditAction edit = new EditAction();
	private DeleteAction delete = new DeleteAction();
	private RefreshAction refresh = new RefreshAction();

	private ToolBarManager toolbar = null;
	protected ListViewer list = null;

	protected final CommonService<T> service;

	protected Logger log = LoggerFactory.getLogger(getClass());

	public AbstractBrowser(Composite parent, CommonService<T> service) {
		super(parent, SWT.NONE);
		this.service = service;
		this.initialize();

		this.addActions(connect, refresh, add, edit, delete);
	}

	public void connect() {
		log.info("connect() not implements");
	}

	public void add() {
		log.info("add() not implements");
	}

	public void edit() {
		log.info("edit() not implements");
	}

	public void delete() {
		java.util.List<T> list = this.getSelectedObjects();
		log.info("selection: " + list);
		for (T o : list) {
			service.remove(o);
		}
		try {
			service.store();
		} catch (IOException e) {
			e.printStackTrace();
		}
		this.setInput(service);
	}

	public void refresh() {
		this.setInput(service);
	}

	protected ActionService getActionService() {
		return DBQApplication.getApplication().getContext().getActionService();
	}

	private void setInput(CommonService<T> service) {
		CommonObject[] a = service.getAllObjects().toArray(new CommonObject[0]);
		Arrays.sort(a, BoUtils.getNameComparator());
		this.list.setInput(a);
	}

	@Override
	public void selectionChanged(SelectionChangedEvent e) {
		int size = this.getSelection().size();
		switch (size) {
		case 0:
			SWTUtils.setEnabled(true, connect, add);
			SWTUtils.setEnabled(false, edit, delete);
			break;
		case 1:
			SWTUtils.setEnabled(true, connect, add, edit, delete);
			break;
		default:
			SWTUtils.setEnabled(false, connect, edit);
			SWTUtils.setEnabled(true, add, delete);
			break;
		}
	}

	protected String getSelectedObjectName() {
		IStructuredSelection sel = this.getSelection();
		if (sel.isEmpty()) {
			return null;
		} else {
			return ((T) sel.iterator().next()).getName();
		}
	}

	protected java.util.List<T> getSelectedObjects() {
		IStructuredSelection select = this.getSelection();
		if (select.isEmpty()) {
			return null;
		} else {
			return select.toList();
		}
	}

	protected IStructuredSelection getSelection() {
		return (IStructuredSelection) list.getSelection();
	}

	protected void addActions(IAction... actions) {
		for (IAction a : actions) {
			this.toolbar.add(a);
		}
		this.toolbar.update(true);
	}

	private void initialize() {
		GridLayout layout = new GridLayout();
		layout.makeColumnsEqualWidth = false;
		layout.numColumns = 1;
		layout.marginWidth = 0;
		layout.marginHeight = 0;
		this.setLayout(layout);

		GridData d = null;
		{
			d = new GridData(GridData.FILL_HORIZONTAL);
			d.verticalSpan = 1;
			d.horizontalSpan = 1;

			ToolBar tb = new ToolBar(this, SWT.WRAP);
			tb.setLayoutData(d);

			toolbar = new ToolBarManager(tb);
		}

		{
			d = new GridData(GridData.FILL_BOTH);
			d.verticalSpan = 1;
			d.horizontalSpan = 1;

			List swtList = new List(this, SWT.MULTI | SWT.BORDER);
			list = new ListViewer(swtList);
			list.getList().setLayoutData(d);
			list.addSelectionChangedListener(this);

			list.setContentProvider(new ArrayContentProvider());
			list.setLabelProvider(new LabelProvider() {
				@Override
				public String getText(Object element) {
					return ((CommonObject) element).getName();
				}
			});
			this.setInput(service);
		}
	}

	private class ConnectAction extends Action {
		public ConnectAction() {
			this.setText("Connect");
			this.setEnabled(true);
		}

		public void run() {
			connect();
		}
	}

	private class AddAction extends Action {
		public AddAction() {
			this.setText("Add");
			this.setEnabled(true);
		}

		public void run() {
			add();
		}
	}

	private class EditAction extends Action {
		public EditAction() {
			this.setText("Edit");
			this.setEnabled(false);
		}

		public void run() {
			edit();
		}
	}

	private class DeleteAction extends Action {
		public DeleteAction() {
			this.setText("Delete");
			this.setEnabled(false);
		}

		public void run() {
			delete();
		}
	}

	private class RefreshAction extends Action {
		public RefreshAction() {
			this.setText("Refresh");
		}

		public void run() {
			refresh();
		}
	}
}
